package com.kyzh.core.uis

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.annotation.TargetApi
import android.content.Context
import android.graphics.*
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.view.animation.PathInterpolatorCompat
import com.kyzh.core.R
import org.jetbrains.anko.sp

/**
 * Created by tanfujun on 15/9/4.
 */
class AnimDownloadProgressButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {


    //背景画笔
    private var mBackgroundPaint: Paint? = null
    //按钮文字画笔
    @Volatile
    private var mTextPaint: Paint? = null
    //第一个点画笔
    private var mDot1Paint: Paint? = null
    //第二个点画笔
    private var mDot2Paint: Paint? = null


    //背景颜色
    private var mBackgroundColor: IntArray? = null
    private var mOriginBackgroundColor: IntArray? = null
    //下载中后半部分后面背景颜色
    private var mBackgroundSecondColor: Int = 0
    //文字颜色
    private var mTextColor: Int = 0
    //覆盖后颜色
    var textCoverColor: Int = 0
    //文字大小
    private var mAboveTextSize = 36f


    var progress = -1f
    private var mToProgress: Float = 0.toFloat()
    var maxProgress: Int = 0
    var minProgress: Int = 0
    private var mProgressPercent: Float = 0.toFloat()

    var buttonRadius=1000f

    //两个点向右移动距离
    private var mDot1transX: Float = 0.toFloat()
    private var mDot2transX: Float = 0.toFloat()

    private var mBackgroundBounds: RectF? = null
    private var mFillBgGradient: LinearGradient? = null
    private var mProgressBgGradient: LinearGradient? = null
    private var mProgressTextGradient: LinearGradient? = null

    //点运动动画
    private var mDotAnimationSet: AnimatorSet? = null
    //下载平滑动画
    private var mProgressAnimation: ValueAnimator? = null

    //记录当前文字
    private var mCurrentText = ""

    private lateinit var mDefaultController: ButtonController

    private var mCustomerController: ButtonController? = null


    private var mState: Int = 0

    //状态确实有改变
    //开启两个点动画
    var state: Int
        get() = mState
        set(state) {
            if (mState != state) {
                this.mState = state
                invalidate()
                when (state) {
                    NORMAL -> mDotAnimationSet?.cancel()
                    DOWNLOADING -> mDotAnimationSet?.cancel()
                }
            }

        }

    init {
        if (isInEditMode) {
            initController()
        } else {
            initController()
            initAttrs(context, attrs)
            init()
            setupAnimations()
        }

    }

    private fun initController() {
        mDefaultController = DefaultButtonController()
    }

    override fun drawableStateChanged() {
        super.drawableStateChanged()
        val buttonController = switchController()
        if (buttonController.enablePress()) {
            if (mOriginBackgroundColor == null) {
                mOriginBackgroundColor = IntArray(2)
                mOriginBackgroundColor!![0] = mBackgroundColor?.get(0)?:0
                mOriginBackgroundColor!![1] = mBackgroundColor?.get(1)?:1
            }
            if (this.isPressed) {
                val pressColorleft = buttonController.getPressedColor(mBackgroundColor?.get(0)?:0)
                val pressColorright = buttonController.getPressedColor(mBackgroundColor?.get(1)?:1)
                if (buttonController.enableGradient()) {
                    initGradientColor(pressColorleft, pressColorright)
                } else {
                    initGradientColor(pressColorleft, pressColorleft)
                }
            } else {
                if (buttonController.enableGradient()) {
                    initGradientColor(mOriginBackgroundColor!![0], mOriginBackgroundColor!![1])
                } else {
                    initGradientColor(mOriginBackgroundColor!![0], mOriginBackgroundColor!![0])
                }
            }
            invalidate()
        }

    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {

        val a = context.obtainStyledAttributes(attrs, R.styleable.AnimDownloadProgressButton)
        val bgColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_backgroud_color, resources.getColor(R.color.colorPrimary))
        //初始化背景颜色数组
        initGradientColor(bgColor, bgColor)
        mBackgroundSecondColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_backgroud_second_color, Color.LTGRAY)
        mAboveTextSize = a.getFloat(R.styleable.AnimDownloadProgressButton_progressbtn_text_size, 36f)
        mTextColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_text_color, bgColor)
        textCoverColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_text_covercolor, Color.WHITE)
        val enableGradient = a.getBoolean(R.styleable.AnimDownloadProgressButton_progressbtn_enable_gradient, false)
        val enablePress = a.getBoolean(R.styleable.AnimDownloadProgressButton_progressbtn_enable_press, false)
        (mDefaultController as DefaultButtonController).setEnableGradient(enableGradient).setEnablePress(enablePress)
        if (enableGradient) {
            initGradientColor(mDefaultController.getLighterColor(mBackgroundColor!![0]), mBackgroundColor!![0])
        }
        a.recycle()
    }

    private fun init() {

        maxProgress = 100
        minProgress = 0
        progress = 0f


        //设置背景画笔
        mBackgroundPaint = Paint()
        mBackgroundPaint?.isAntiAlias = true
        mBackgroundPaint?.style = Paint.Style.FILL

        //设置文字画笔
        mTextPaint = Paint()
        mTextPaint?.isAntiAlias = true
        mTextPaint?.textSize = sp(mAboveTextSize).toFloat()
        //解决文字有时候画不出问题
        setLayerType(View.LAYER_TYPE_SOFTWARE, mTextPaint)

        //设置第一个点画笔
        mDot1Paint = Paint()
        mDot1Paint?.isAntiAlias = true
        mDot1Paint?.textSize = sp(mAboveTextSize).toFloat()

        //设置第二个点画笔
        mDot2Paint = Paint()
        mDot2Paint?.isAntiAlias = true
        mDot2Paint?.textSize = sp(mAboveTextSize).toFloat()


        //初始化状态设为NORMAL
        mState = NORMAL
        invalidate()

    }

    //初始化渐变色
    private fun initGradientColor(leftColor: Int, rightColor: Int): IntArray {
        mBackgroundColor = IntArray(2)
        mBackgroundColor!![0] = leftColor
        mBackgroundColor!![1] = rightColor
        return mBackgroundColor!!
    }


    private fun setupAnimations() {

        //两个点向右移动动画
        val dotMoveAnimation = ValueAnimator.ofFloat(0f, 20.toFloat())
        val pathInterpolator = PathInterpolatorCompat.create(0.11f, 0f, 0.12f, 1f)
        dotMoveAnimation.interpolator = pathInterpolator
        dotMoveAnimation.addUpdateListener { animation ->
            val transX = animation.animatedValue as Float
            mDot1transX = transX
            mDot2transX = transX
            invalidate()
        }
        dotMoveAnimation.duration = 1243
        dotMoveAnimation.repeatMode = ValueAnimator.RESTART
        dotMoveAnimation.repeatCount = ValueAnimator.INFINITE


        //两个点渐显渐隐动画
        val dotAlphaAnim = ValueAnimator.ofInt(0, 1243).setDuration(1243)
        dotAlphaAnim.addUpdateListener { animation ->
            val time = dotAlphaAnim.animatedValue as Int
            val dot1Alpha = calculateDot1AlphaByTime(time)
            val dot2Alpha = calculateDot2AlphaByTime(time)
            mDot1Paint?.color = textCoverColor
            mDot2Paint?.color = textCoverColor
            mDot1Paint?.alpha = dot1Alpha
            mDot2Paint?.alpha = dot2Alpha
        }


        dotAlphaAnim.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                mDot1Paint?.alpha = 0
                mDot2Paint?.alpha = 0
            }

            override fun onAnimationEnd(animation: Animator) {}

            override fun onAnimationCancel(animation: Animator) {

            }

            override fun onAnimationRepeat(animation: Animator) {

            }
        })
        dotAlphaAnim.repeatMode = ValueAnimator.RESTART
        dotAlphaAnim.repeatCount = ValueAnimator.INFINITE
        //两个点的动画集合
        mDotAnimationSet = AnimatorSet()
        mDotAnimationSet?.playTogether(dotAlphaAnim, dotMoveAnimation)

        //ProgressBar的动画
        mProgressAnimation = ValueAnimator.ofFloat(0f, 1f).setDuration(500)
        mProgressAnimation?.addUpdateListener { animation ->
            val timepercent = animation.animatedValue as Float
            progress = (mToProgress - progress) * timepercent + progress
            invalidate()
        }


    }

    //第一个点透明度计算函数
    private fun calculateDot2AlphaByTime(time: Int): Int {
        val alpha: Int
        if (time in 0..83) {
            val DAlpha = 255.0 / 83.0 * time
            alpha = DAlpha.toInt()
        } else if (time in 84..1000) {
            alpha = 255
        } else if (time in 1001..1083) {
            val DAlpha = -255.0 / 83.0 * (time - 1083)
            alpha = DAlpha.toInt()
        } else if (time in 1084..1243) {
            alpha = 0
        } else {
            alpha = 255
        }
        return alpha
    }

    //第二个点透明度计算函数
    private fun calculateDot1AlphaByTime(time: Int): Int {
        val alpha: Int
        if (time in 0..160) {
            alpha = 0
        } else if (time in 161..243) {
            val DAlpha = 255.0 / 83.0 * (time - 160)
            alpha = DAlpha.toInt()
        } else if (time in 244..1160) {
            alpha = 255
        } else if (time in 1161..1243) {
            val DAlpha = -255.0 / 83.0 * (time - 1243)
            alpha = DAlpha.toInt()
        } else {
            alpha = 255
        }
        return alpha
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (!isInEditMode) {
            drawing(canvas)
        }
    }

    private fun drawing(canvas: Canvas) {
        drawBackground(canvas)
        drawTextAbove(canvas)
    }

    private fun drawBackground(canvas: Canvas) {
        mBackgroundBounds = RectF()
        mBackgroundBounds?.left = 2f
        mBackgroundBounds?.top = 2f
        mBackgroundBounds?.right = (measuredWidth - 2).toFloat()
        mBackgroundBounds?.bottom = (measuredHeight - 2).toFloat()

        val buttonController = switchController()

        //color
        when (mState) {
            NORMAL -> {
                if (buttonController.enableGradient()) {
                    mFillBgGradient = LinearGradient(0f, (measuredHeight / 2).toFloat(), measuredWidth.toFloat(), (measuredHeight / 2).toFloat(),
                            mBackgroundColor!!, floatArrayOf(),
                            Shader.TileMode.CLAMP)
                    mBackgroundPaint?.shader = mFillBgGradient
                } else {
                    if (mBackgroundPaint?.shader != null) {
                        mBackgroundPaint?.shader = null
                    }
                    mBackgroundPaint?.color = mBackgroundColor!![0]
                }
                canvas.drawRoundRect(mBackgroundBounds!!, buttonRadius, buttonRadius, mBackgroundPaint!!)
            }
            DOWNLOADING -> {
                if (buttonController.enableGradient()) {
                    mProgressPercent = progress / (maxProgress + 0f)
                    val colorList = intArrayOf(mBackgroundColor!![0], mBackgroundColor!![1], mBackgroundSecondColor)
                    mProgressBgGradient = LinearGradient(0f, 0f, measuredWidth.toFloat(), 0f,
                            colorList,
                            floatArrayOf(0f, mProgressPercent, mProgressPercent + 0.001f),
                            Shader.TileMode.CLAMP
                    )
                    mBackgroundPaint?.shader = mProgressBgGradient
                } else {
                    mProgressPercent = progress / (maxProgress + 0f)
                    mProgressBgGradient = LinearGradient(0f, 0f, measuredWidth.toFloat(), 0f,
                            intArrayOf(mBackgroundColor!![0], mBackgroundSecondColor),
                            floatArrayOf(mProgressPercent, mProgressPercent + 0.001f),
                            Shader.TileMode.CLAMP
                    )
                    mBackgroundPaint?.color = mBackgroundColor!![0]
                    mBackgroundPaint?.shader = mProgressBgGradient
                }
                canvas.drawRoundRect(mBackgroundBounds!!, buttonRadius, buttonRadius, mBackgroundPaint!!)
            }
        }
    }

    private fun drawTextAbove(canvas: Canvas) {
        val y = canvas.height / 2 - ((mTextPaint?.descent()?.div(2)!!) + (mTextPaint?.ascent()?.div(2)!!))

        val textWidth = mTextPaint?.measureText(mCurrentText)
        //color
        when (mState) {
            NORMAL -> {
                mTextPaint?.shader = null
                mTextPaint?.color = textCoverColor
                mTextPaint?.let { canvas.drawText(mCurrentText, (measuredWidth - textWidth!!) / 2, y, it) }
            }
            DOWNLOADING -> {

                //进度条压过距离
                val coverlength = measuredWidth * mProgressPercent
                //开始渐变指示器
                val indicator1 = measuredWidth / 2 - textWidth!! / 2
                //结束渐变指示器
                val indicator2 = measuredWidth / 2 + textWidth / 2
                //文字变色部分的距离
                val coverTextLength = textWidth / 2 - measuredWidth / 2 + coverlength
                val textProgress = coverTextLength / textWidth
                if (coverlength <= indicator1) {
                    mTextPaint?.shader = null
                    mTextPaint?.color = mTextColor
                } else if (indicator1 < coverlength && coverlength <= indicator2) {
                    mProgressTextGradient = LinearGradient((measuredWidth - textWidth) / 2, 0f, (measuredWidth + textWidth) / 2, 0f,
                            intArrayOf(textCoverColor, mTextColor),
                            floatArrayOf(textProgress, textProgress + 0.001f),
                            Shader.TileMode.CLAMP)
                    mTextPaint?.color = mTextColor
                    mTextPaint?.shader = mProgressTextGradient
                } else {
                    mTextPaint?.shader = null
                    mTextPaint?.color = textCoverColor
                }
                canvas.drawText(mCurrentText, (measuredWidth - textWidth) / 2, y, mTextPaint!!)
            }
        }

    }

    private fun switchController(): ButtonController {
        return if (mCustomerController != null) {
            mCustomerController!!
        } else {
            mDefaultController
        }
    }

    /**
     * 设置按钮文字
     */
    fun setCurrentText(charSequence: CharSequence) {
        mCurrentText = charSequence.toString()
        invalidate()
    }


    /**
     * 设置带下载进度的文字
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    fun setProgressText(text: String, progress: Float) {
        if (progress >= minProgress && progress < maxProgress) {
            mCurrentText = text
            mToProgress = progress
            if (mProgressAnimation?.isRunning==true) {
                mProgressAnimation?.start()
            } else {
                mProgressAnimation?.start()
            }
        } else if (progress < minProgress) {
            this.progress = 0f
        } else if (progress >= maxProgress) {
            this.progress = 100f
            mCurrentText = text
            invalidate()
        }
    }

    /**
     * Sometimes you should use the method to avoid memory leak
     */
    fun removeAllAnim() {
        mDotAnimationSet?.cancel()
        mDotAnimationSet?.removeAllListeners()
        mProgressAnimation?.cancel()
        mProgressAnimation?.removeAllListeners()
    }


    fun setProgressBtnBackgroundColor(color: Int) {
        initGradientColor(color, color)
    }


    fun setProgressBtnBackgroundSecondColor(color: Int) {

        mBackgroundSecondColor = color
    }

    fun getTextColor(): Int {
        return mTextColor
    }

    override fun setTextColor(textColor: Int) {
        mTextColor = textColor
    }

    fun enabelDefaultPress(enable: Boolean) {
        (mDefaultController as DefaultButtonController).setEnablePress(enable)
    }

    fun enabelDefaultGradient(enable: Boolean) {
        (mDefaultController as DefaultButtonController).setEnableGradient(enable)
        initGradientColor(mDefaultController.getLighterColor(mBackgroundColor!![0]), mBackgroundColor!![0])
    }

    override fun setTextSize(size: Float) {
        mAboveTextSize = size
        mTextPaint?.textSize = size
    }

    override fun getTextSize(): Float {
        return mAboveTextSize
    }


    override fun onRestoreInstanceState(state: Parcelable) {
        val ss = state as SavedState
        super.onRestoreInstanceState(ss.getSuperState())
        mState = ss.state
        progress = ss.progress.toFloat()
        mCurrentText = ss.currentText.toString()
    }

    override fun onSaveInstanceState(): Parcelable? {
        val superState = super.onSaveInstanceState()
        return superState?.let { SavedState(it, progress.toInt(), mState, mCurrentText) }
    }

    class SavedState : BaseSavedState {

        var progress: Int = 0
        var state: Int = 0
        var currentText: String =""

        constructor(parcel: Parcelable, progress: Int, state: Int, currentText: String) : super(parcel) {
            this.progress = progress
            this.state = state
            this.currentText = currentText
        }

        private constructor(`in`: Parcel) : super(`in`) {
            progress = `in`.readInt()
            state = `in`.readInt()
            currentText = `in`.readString()?:""
        }

        override fun writeToParcel(out: Parcel, flags: Int) {
            super.writeToParcel(out, flags)
            out.writeInt(progress)
            out.writeInt(state)
            out.writeString(currentText)
        }

        companion object{
            @JvmField val CREATOR : Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState>{
                override fun createFromParcel(source: Parcel): SavedState {
                    return SavedState(source)
                }

                override fun newArray(size: Int): Array<SavedState> {
                    return newArray(size)
                }

            }
        }

    }

    companion object {

        //普通状态
        val NORMAL = 0
        //下载中
        val DOWNLOADING = 1

    }

    inner class DefaultButtonController : ButtonController {


        private var enablePress: Boolean = false

        private var enableGradient: Boolean = false

        /**
         * 获得按下的颜色（明度降低10%）
         *
         * @param color
         * @return int
         */
        override fun getPressedColor(color: Int): Int {
            val hsv = FloatArray(3)
            Color.colorToHSV(color, hsv)
            hsv[2] -= 0.1f
            return Color.HSVToColor(hsv)
        }

        /**
         * 由右边的颜色算出左边的颜色（左边的颜色比右边的颜色降饱和度30%，亮度增加30%）
         * +
         *
         * @param color
         * @return
         */
        override fun getLighterColor(color: Int): Int {
            val hsv = FloatArray(3)
            Color.colorToHSV(color, hsv)
            hsv[1] -= 0.3f
            hsv[2] += 0.3f
            return Color.HSVToColor(hsv)
        }


        override fun enablePress(): Boolean {
            return enablePress
        }

        override fun enableGradient(): Boolean {
            return enableGradient
        }

        fun setEnablePress(enablePress: Boolean): DefaultButtonController {
            this.enablePress = enablePress
            return this
        }

        fun setEnableGradient(enableGradient: Boolean): DefaultButtonController {
            this.enableGradient = enableGradient
            return this
        }
    }

    interface ButtonController {
        fun getPressedColor(color: Int): Int

        fun getLighterColor(color: Int): Int

        fun enablePress(): Boolean

        fun enableGradient(): Boolean


    }


}
